#include "mutex.h"

Thread_Mutex::Thread_Mutex()
	: m_remove( false )
{
	pthread_mutexattr_t mutex_attr;
	pthread_condattr_t  cond_attr;

	pthread_mutexattr_init( &mutex_attr );
	pthread_mutex_init( &m_lock, &mutex_attr );
	pthread_condattr_init( &cond_attr );
	pthread_cond_init( &m_cond, &cond_attr );
}

Thread_Mutex::Thread_Mutex( const pthread_mutexattr_t * mutex_attr,
							const pthread_condattr_t * cond_attr )
    : m_remove( false )
{
	pthread_mutex_init( &m_lock, mutex_attr );
	pthread_cond_init( &m_cond, cond_attr );
}

Thread_Mutex::~Thread_Mutex() throw()
{
    if( !m_remove )
    {
        m_remove = true;
        pthread_mutex_destroy( &m_lock );
        pthread_cond_destroy( &m_cond );
    }
}

int Thread_Mutex::acquire()
{
    return pthread_mutex_lock( &m_lock );
}

int Thread_Mutex::acquire( const Time_Value & timeout )
{
    timespec_t ts = timeout;
    return pthread_mutex_timedlock( &m_lock, &ts );
}

int Thread_Mutex::release()
{
    return pthread_mutex_unlock( &m_lock );
}

void Thread_Mutex::wait() const
{
	pthread_cond_wait( &m_cond, &m_lock );
}

void Thread_Mutex::wait( const Time_Value & delay ) const
{
	timespec_t abstime = (timespec_t)Time_Value::timeofday();
	abstime.tv_sec += delay.sec();
	abstime.tv_nsec += delay.usec() * 1000;
	pthread_cond_timedwait( &m_cond, &m_lock, &abstime );
}

void Thread_Mutex::notify()
{
	pthread_cond_signal( &m_cond );
}

void Thread_Mutex::notify_all()
{
	pthread_cond_broadcast( &m_cond );
}

Thread_RW_Mutex::Thread_RW_Mutex( const pthread_rwlockattr_t * attr )
{
    pthread_rwlock_init( &m_lock, attr );
}

Thread_RW_Mutex::~Thread_RW_Mutex() throw()
{
    pthread_rwlock_destroy( &m_lock );
}

int Thread_RW_Mutex::wr_acquire()
{
    return pthread_rwlock_wrlock( &m_lock );
}

int Thread_RW_Mutex::rd_acquire()
{
    return pthread_rwlock_rdlock( &m_lock );
}

int Thread_RW_Mutex::release()
{
    return pthread_rwlock_unlock( &m_lock );
}

Write_Guard::Write_Guard( Thread_RW_Mutex & lock )
    : m_lock( &lock )
{
    m_lock->wr_acquire();
}

Write_Guard::~Write_Guard() throw()
{
    m_lock->release();
}

Read_Guard::Read_Guard( Thread_RW_Mutex & lock )
    : m_lock( &lock )
{
    m_lock->rd_acquire();
}

Read_Guard::~Read_Guard() throw()
{
    m_lock->release();
}

